package com.good.domain.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.good.domain.Utils.RequestUtil;
import com.good.domain.config.WebLogEnum;
import com.good.domain.entity.AdminLog;
import com.good.domain.mapper.AdminLogMapper;
import com.good.domain.service.IAdminLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 大钊
 * @since 2022-09-04
 */
@Service
public class AdminLogServiceImpl extends ServiceImpl<AdminLogMapper, AdminLog> implements IAdminLogService {
    @Autowired
    private AdminLogMapper adminLogMapper;

    public static String[] ignoreKeywords = {"password", "passWord", "pass_word", "PASS_WORD", "PASSWORD"};

    private static final Integer MAX_PARAM = 500;

    @Override
    public AdminLog getBaseAdminLog() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        AdminLog adminLog = new AdminLog();
        String requestUrl = request.getRequestURL().toString();
        adminLog.setUrl(requestUrl);
        adminLog.setMethod(StringUtils.hasLength(requestUrl) ? requestUrl.substring(requestUrl.lastIndexOf("/") + 1) : null);
        adminLog.setInsertTime(LocalDateTime.now());
        adminLog.setMethodType(request.getMethod());
        adminLog.setContent("通用日志记录");
        WebLogEnum[] values = WebLogEnum.values();
        for (WebLogEnum value : values) {
            if (request.getRequestURL().toString().contains(value.getUrl())) {
                adminLog.setModuleId(value.getModuleId());
                adminLog.setModuleName(value.getModuleName());
            }
        }
        adminLog.setIp(RequestUtil.getIp());
        return adminLog;
    }

    @Override
    public void setAdminLog(Long uid, String content, Object... params) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        AdminLog adminLog = new AdminLog();
        String requestUrl = request.getRequestURL().toString();
        adminLog.setUrl(requestUrl);
        adminLog.setMethod(StringUtils.hasLength(requestUrl) ? requestUrl.substring(requestUrl.lastIndexOf("/") + 1) : null);
        adminLog.setInsertTime(LocalDateTime.now());
        adminLog.setMethodType(request.getMethod());

        StringBuilder requestParamBuilder = new StringBuilder();
        if (params != null) {
            for (Object param : params) {
                if (param instanceof HttpServletResponse) {
                    continue;
                }
                if (param instanceof MultipartFile) {
                    continue;
                }
                try {
                    requestParamBuilder.append(JSON.toJSONString(param)).append("|");
                } catch (JSONException e) {
                    requestParamBuilder.append(param).append("|");
                }
            }
        }
        if (requestParamBuilder.lastIndexOf("|") != -1) {
            requestParamBuilder.deleteCharAt(requestParamBuilder.lastIndexOf("|"));
        }
        adminLog.setParam(ignoreKeywords(requestParamBuilder.toString()));
        WebLogEnum[] values = WebLogEnum.values();
        for (WebLogEnum value : values) {
            if (request.getRequestURI().startsWith(value.getUrl())) {
                adminLog.setModuleId(value.getModuleId());
                adminLog.setModuleName(value.getModuleName());
            }
        }
        adminLog.setIp(RequestUtil.getIp());
        adminLog.setUid(uid);
        if (StringUtils.hasLength(content)) {
            adminLog.setContent(content);
        } else {
            adminLog.setContent("通用日志记录");
        }
        if (adminLog.getParam().length() < MAX_PARAM) {
            adminLogMapper.insert(adminLog);
        }
    }

    @Override
    public IPage<HashMap<String, Object>> pageInfo(IPage<HashMap<String, Object>> page, Long uid, LocalDateTime startTime, LocalDateTime endTime, Integer moduleId, String keywords) {
        return adminLogMapper.pageInfo(page, uid, startTime, endTime, moduleId, keywords);
    }

    @Override
    public String ignoreKeywords(String param) {
        for (String ignoreKeyword : ignoreKeywords) {
            //2022年5月23日 出现敏感词时,直接过滤掉,不替换参数
//            String regx = "(\"" + ignoreKeyword + "\":\")(([\\u4e00-\\u9fa5]|[\\w]|[\\W]!\")*)(\")";
            String regx = "(\"" + ignoreKeyword + "\":\")(([\\u4e00-\\u9fa5]|[\\w]|[\\W]!\")*)(\"),?";
            Pattern compile = Pattern.compile(regx);
            Matcher matcher = compile.matcher(param);
            StringBuilder result = new StringBuilder();
            while (matcher.find()) {
                //2022年5月23日 出现敏感词时,直接过滤掉,不替换参数
//                String group1 = matcher.group(1);
//                String group4 = matcher.group(4);
//                matcher.appendReplacement(result, group1 + "****" + group4);
                matcher.appendReplacement(result, "");
            }
            matcher.appendTail(result);
            param = result.toString();
        }
        return param;
    }
}
